﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Web.Caching;
using System.Web.UI;
using System.Web.UI.WebControls;
using EPiServer;
using EPiServer.BaseLibrary;
using EPiServer.BaseLibrary.Serialization;
using EPiServer.Configuration;
using EPiServer.Core.Html.StringParsing;
using EPiServer.Framework.Initialization;
using EPiServer.Globalization;
using EPiServer.Implementation;
using EPiServer.Shell;
using EPiServer.Shell.Modules;
using EPiServer.Shell.Web.Resources;
using EPiServer.SpecializedProperties;

namespace OpenWaves.Testing
{
    public static class EPiServerInfrastructureStub
    {
        public static void EnsureSetup()
        {
            SiteMappingConfiguration.Instance = new SiteMappingConfiguration();
            SiteMappingConfiguration.Instance.SiteId = "*";

            SystemLanguage.Instance = new FakeSystemLanguage();
            ContentLanguage.Instance = new FakeContentLanguage();
            UserInterfaceLanguage.Instance = new FakeUserInterfaceLanguage();

            var classFactory = new DummyClassFactory("DefaultBLF");
            classFactory.RegisterClass(typeof(IRuntimeCache), typeof(NullRuntimeCache));
            ClassFactory.Instance = classFactory;

            ShellContext.Instance.Container.GetExportedValue<ModuleTable>().Add(new ShellModule("Shell", "", ""));
            ShellContext.Instance.Container.GetExportedValue<ClientResourceAggregator>();
            Settings.Instance = new Settings
            {
                PageStartId = 1
            };
        }

        public class FakeSystemLanguage : SystemLanguage
        {
            public override CultureInfo SetCulture(string priorityLanguage)
            {
                return CultureInfo.CurrentUICulture;
            }
        }

        public class FakeContentLanguage : ContentLanguage
        {
            public override CultureInfo SetCulture(string priorityLanguage)
            {
                return CultureInfo.CurrentUICulture;
            }
        }

        public class FakeUserInterfaceLanguage : UserInterfaceLanguage
        {
            public override CultureInfo SetCulture(string priorityLanguage)
            {
                return CultureInfo.CurrentUICulture;
            }
        }

        class DummyClassFactory : DefaultClassFactory, IBaseLibraryFactory
        {
            public DummyClassFactory(string id)
                : base(id)
            {
                base.RegisterClass(typeof(IContext), typeof(DefaultContext));
                /*base.RegisterClass(typeof(IRepository), typeof(DefaultRepository));
                base.RegisterClass(typeof(ISession), typeof(DefaultSession));
                base.RegisterClass(typeof(IItem), typeof(DefaultItem));
                base.RegisterClass(typeof(IItemList<,>), typeof(DefaultItemList<,>));
                base.RegisterClass(typeof(ISchema), typeof(DefaultSchema));*/
            }

            #region IBaseLibraryFactory Members

            public IItem CreateItem(object id, string name)
            {
                return (IItem)base.CreateInstance(typeof(IItem), new object[] { id, name });
            }

            public IItemList<IDTYPE, ITEMTYPE> CreateItemList<IDTYPE, ITEMTYPE>(object containerId)
                where ITEMTYPE : IItem
            {
                return
                    (IItemList<IDTYPE, ITEMTYPE>)
                    base.CreateInstance(typeof(IItemList<IDTYPE, ITEMTYPE>), new object[] { containerId, false });
            }

            public IItemList<IDTYPE, ITEMTYPE> CreateItemList<IDTYPE, ITEMTYPE>(string containerPath)
                where ITEMTYPE : IItem
            {
                return
                    (IItemList<IDTYPE, ITEMTYPE>)
                    base.CreateInstance(typeof(IItemList<IDTYPE, ITEMTYPE>), new object[] { containerPath, false });
            }

            public IItemList<IDTYPE, ITEMTYPE> CreateItemList<IDTYPE, ITEMTYPE>(object containerId,
                                                                                bool includeSubclasses)
                where ITEMTYPE : IItem
            {
                return
                    (IItemList<IDTYPE, ITEMTYPE>)
                    base.CreateInstance(typeof(IItemList<IDTYPE, ITEMTYPE>),
                                        new object[] { containerId, includeSubclasses });
            }

            public IItemList<IDTYPE, ITEMTYPE> CreateItemList<IDTYPE, ITEMTYPE>(string containerPath,
                                                                                bool includeSubclasses)
                where ITEMTYPE : IItem
            {
                return
                    (IItemList<IDTYPE, ITEMTYPE>)
                    base.CreateInstance(typeof(IItemList<IDTYPE, ITEMTYPE>),
                                        new object[] { containerPath, includeSubclasses });
            }

            public IRepository CreateRepository()
            {
                return (IRepository)base.CreateInstance(typeof(IRepository), new object[0]);
            }

            public IContext CreateContext()
            {
                return (IContext)base.CreateInstance(typeof(IContext), new object[0]);
            }


            public ISchema CreateSchema(string schemaId)
            {
                return (ISchema)base.CreateInstance(typeof(ISchema), new object[] { schemaId });
            }

            public ISession CreateSession(IObjectStore objectStore)
            {
                return (ISession)base.CreateInstance(typeof(ISession), new object[] { objectStore });
            }

            #endregion
        }

        public class NullRuntimeCache : IRuntimeCache
        {
            #region IRuntimeCache Members

            public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration,
                               TimeSpan slidingExpiration, CacheItemPriority priority)
            {
            }

            public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration,
                               TimeSpan slidingExpiration, CacheItemPriority priority,
                               CacheItemRemovedCallback onRemoveCallback)
            {
            }

            public object Add(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration,
                              TimeSpan slidingExpiration, CacheItemPriority priority)
            {
                return null;
            }

            public object Add(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration,
                              TimeSpan slidingExpiration, CacheItemPriority priority,
                              CacheItemRemovedCallback onRemoveCallback)
            {
                return null;
            }

            public void Remove(string key)
            {
            }

            public object Get(string key)
            {
                return null;
            }

            public void Clear()
            {
            }

            #endregion
        }

        public class FragmentParserScope : IDisposable
        {
            private readonly Func<IFragmentParser> previousParserConstructor;

            public FragmentParserScope(Func<IFragmentParser> createParser)
            {
                previousParserConstructor = FragmentParserFactory.DefaultParserConstructor;
                FragmentParserFactory.DefaultParserConstructor = createParser;
            }

            public void Dispose()
            {
                FragmentParserFactory.DefaultParserConstructor = previousParserConstructor;
            }
        }

        public class NullFragmentParser : IFragmentParser
        {
            public StringFragmentCollection Parse(string content, FragmentParserMode parserMode, bool evaluateHash)
            {
                return new StringFragmentCollection((IEnumerable<IStringFragment>) new[] { new StaticNullFragment(content) });
            }

            private class StaticNullFragment : IStringFragment
            {
                private readonly string value;

                public string InternalFormat
                {
                    get
                    {
                        return this.value;
                    }
                }

                public IList<Guid> ReferencedPermanentLinkIds
                {
                    get
                    {
                        return new List<Guid>();
                    }
                }

                public StaticNullFragment(string str)
                {
                    this.value = str;
                }

                public string GetEditFormat()
                {
                    return this.InternalFormat;
                }

                public string GetViewFormat()
                {
                    return this.InternalFormat;
                }

                public string GetOnPageEditFormat()
                {
                    return this.InternalFormat;
                }

                public Control GetControl(PageBase hostPage)
                {
                    return new Literal
                               {
                                   Text = this.InternalFormat
                               };
                }

                public void RemapPermanentLinkReferences(IDictionary<Guid, Guid> idMap)
                {
                }
            }
        }
    }
}